define(function(require,exports,module){

  var eventSplitter = /\s+/;

  function Event(){};

  Event.prototype.on = function(events,callback,context){
    var cache,list,event;
    if(!callback) return this;
    cache = this.__events || (this.__events = {});
    events = events.split(eventSplitter);
    while(event = events.shift()){
      list = cache[event] || (cache[event] = []);
      list.push(callback,context);
    }
    return this;
  }

  Event.prototype.off = function(events,callback,context){
    var cache,event,list,i;
    if(!(cache=this.__events)) return this;
    if(!(cache || callback || context)){
      delete this.__events;
      return this;
    }
    events = events ? events.split(eventSplitter) : keys(cache);
    while(event = events.shift()){
      list = cache[event];
      if (!list) continue;
      if (!(callback || context)) {
        delete cache[event];
        continue;
      }
      for (i = list.length - 2; i >= 0; i -= 2) {
        if (!(callback && list[i] !== callback || context && list[i + 1] !== context)) {
          list.splice(i, 2);
        }
      }
    }
    return this;
  };

  Events.prototype.trigger = function(events) {
    var cache, event, all, list, i, len, rest = [], args, returned = {
      status: true
    };
    if (!(cache = this.__events)) return this;
    events = events.split(eventSplitter);
    // Fill up `rest` with the callback arguments.  Since we're only copying
    // the tail of `arguments`, a loop is much faster than Array#slice.
    for (i = 1, len = arguments.length; i < len; i++) {
      rest[i - 1] = arguments[i];
    }
    // For each event, walk through the list of callbacks twice, first to
    // trigger the event, then to trigger any `"all"` callbacks.
    while (event = events.shift()) {
      // Copy callback lists to prevent modification.
      if (all = cache.all) all = all.slice();
      if (list = cache[event]) list = list.slice();
      // Execute event callbacks.
      callEach(list, rest, this, returned);
      // Execute "all" callbacks.
      callEach(all, [ event ].concat(rest), this, returned);
    }
    return returned.status;
  };

  // Mix `Events` to object instance or Class function.
  Events.mixTo = function(receiver) {
    receiver = receiver.prototype || receiver;
    var proto = Events.prototype;
    for (var p in proto) {
      if (proto.hasOwnProperty(p)) {
        receiver[p] = proto[p];
      }
    }
  };

  /*          Helpers
  =============================================
  * */
  var keys = Object.keys;
  if(!keys){
    keys = function(o){
      var result = [];
      for(var name in o){
        if(o.hasOwnProperty(name)){
          result.push(name);
        }
      }
      return result;
    }
  }
  // Execute callbacks
  function callEach(list, args, context, returned) {
    var r;
    if (list) {
      for (var i = 0, len = list.length; i < len; i += 2) {
        r = list[i].apply(list[i + 1] || context, args);
        // trigger will return false if one of the callbacks return false
        r === false && returned.status && (returned.status = false);
      }
    }
  }

  return Event;

});